package com.xjnt.frameworks.plugin.route;

import java.util.List;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.jfinal.config.Routes;
import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log4jLogger;
import com.jfinal.log.Logger;
import com.xjnt.frameworks.annotation.Router;
import com.xjnt.frameworks.utils.ClasserKit;

public class AutoRoutes extends Routes {

	private static final Logger logger = Log4jLogger.getLogger(AutoRoutes.class);

	private boolean autoScan = false;

	/**
	 * 需要过滤的类集合
	 */
	private List<Class<? extends Controller>> excludeClasses = Lists.newArrayList();

	/**
	 * 需要解析的类包
	 */
	private List<String> includeClassPackages = Lists.newArrayList();

	/**
	 * 是否解析Library库中的所有Jar包
	 */
	private boolean includeAllJarsInLib = false;

	/**
	 * 需要解析的Jar包路径集合
	 */
	private List<String> includeJars = Lists.newArrayList();

	/**
	 * 类的默认后缀
	 */
	private String suffix = "Router";
	
	public AutoRoutes autoScan(boolean autoScan){
		this.autoScan = autoScan;
		return this;
	}

	public AutoRoutes addScanPackages(String... classPackages) {
		for (String classPkg : classPackages) {
			includeClassPackages.add(classPkg);
		}
		return this;
	}

	public AutoRoutes addScanPackages(List<String> classPackages) {
		if (null != classPackages && !classPackages.isEmpty()) {
			includeClassPackages.addAll(classPackages);
		}
		return this;
	}

	@SuppressWarnings("unchecked")
	public AutoRoutes addExcludeClasses(Class<? extends Controller>... classes) {
		for (Class<? extends Controller> clazz : classes) {
			excludeClasses.add(clazz);
		}
		return this;
	}

	public AutoRoutes addExcludeClasses(List<Class<? extends Controller>> classes) {
		if (null != classes && !classes.isEmpty()) {
			excludeClasses.addAll(classes);
		}
		return this;
	}

	public AutoRoutes addIncludeJars(String... jars) {
		for (String jar : jars) {
			includeJars.add(jar);
		}
		return this;
	}

	private String getAction(Class<? extends Controller> clazz) {
		Preconditions.checkArgument(clazz.getSimpleName().endsWith(suffix), clazz.getName()
				+ " is not annotated with @Router and not end with " + suffix);
		String action = "/" + StrKit.firstCharToLowerCase(clazz.getSimpleName());
		action = action.substring(0, action.indexOf(suffix));
		return action;
	}

	public AutoRoutes setSuffix(String suffix) {
		this.suffix = suffix;
		return this;
	}

	@Override
	public void config() {
		List<Class<? extends Controller>> routerClasses = ClasserKit.of(Controller.class)
				.scanPackages(includeClassPackages).includeAllJarsInLib(includeAllJarsInLib).injars(includeJars)
				.search();
		Router router;
		for (Class<? extends Controller> clazz : routerClasses) {
			if (excludeClasses.contains(clazz)) {
				continue;
			}
			router = clazz.getAnnotation(Router.class);
			String actionName = null;
			String actionView = null;
			if (null == router) {
				if (!autoScan) {
					continue;
				}
				actionName = getAction(clazz);
				this.add(actionName, clazz);
			} else if (StrKit.notBlank(router.view())) {
				actionName = router.name();
				actionView = router.view();
				this.add(actionName, clazz, actionView);
			} else {
				actionName = router.name();
				this.add(actionName, clazz);
			}
			logger.debug("routes.add(" + actionName + ", " + clazz.getName() + ", " + actionView + ")");
		}
	}
}
